﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#ifndef __ROUTINE_IMP_H__
#define __ROUTINE_IMP_H__

#pragma once

#include "IMasterRoutine.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// CMasterRoutine :
// 1. 异步事件队列维护
// 2. 在线业务功能服务器和业务ID的信息维护
// 3. 在线业务网关id唯一性的验证
// 4. 网关和功能数据中转
class CMasterRoutine : public IMasterRoutine
{
    DECLARE_RTTI_CREATE( CMasterRoutine )
private:
    struct tagSERVICE_SOCKET : public MObject
    {
        uintptr_t   utId;
        Socket_t    sSocket;
    };
    typedef tagSERVICE_SOCKET SERVICE_SOCKET, *PSERVICE_SOCKET;

    typedef CTArray<ULLong>                       ARY_ROUTINEID;

    // hash<--->uuid-string将RID字符串通过HASH64生成摘要值
    typedef CTMap<ULLong, CKVString>              ROUTINEID_MAP, *PROUTINEID_MAP;
    typedef CTMap<ULLong, CKVString>::PAIR        ROUTINEID_MAP_PAIR;
    typedef tagSERVER_CHAIN<ROUTINEID_MAP>        ROUTINEID_MAP_CHAIN;
    // 类型允许连接的功能id
    typedef CTMap<UInt, ARY_ROUTINEID>            TYPE_RID_MAP, *PTYPE_RID_MAP;
    typedef CTMap<UInt, ARY_ROUTINEID>::PAIR      TYPE_RID_MAP_PAIR;
    typedef tagSERVER_CHAIN<TYPE_RID_MAP>         TYPE_RID_MAP_CHAIN;
    // 功能id<--->连接
    typedef CTMap<ULLong, SERVICE_SOCKET>         RID_SOCKET_MAP, *PRID_SOCKET_MAP;
    typedef CTMap<ULLong, SERVICE_SOCKET>::PAIR   RID_SOCKET_MAP_PAIR;
    typedef tagSERVER_CHAIN<RID_SOCKET_MAP>       RID_SOCKET_MAP_CHAIN;
    // 连接<--->功能id
    typedef CTMap<ULLong, ARY_ROUTINEID>          SOCKET_RID_MAP, *PSOCKET_RID_MAP;
    typedef CTMap<ULLong, ARY_ROUTINEID>::PAIR    SOCKET_RID_MAP_PAIR;
    // 服务器id和连接对应关系
    typedef CTMap<UInt, ULLong>                   ID_MAP, *PID_MAP;
    typedef CTMap<UInt, ULLong>::PAIR             ID_MAP_PAIR;
    typedef tagSERVER_CHAIN<ID_MAP>               ID_MAP_CHAIN;
public:
    CMasterRoutine(void);
    virtual ~CMasterRoutine(void);
    // CEventHandler
    virtual UInt OnHandle(Int nEvent, uintptr_t utData, ULLong ullParam) OVERRIDE;
    virtual UInt OnHandle(Int nEvent, CEventBase& EventRef, ULLong ullParam) OVERRIDE;
    virtual UInt OnHandle(Int nEvent, CStream& Stream, ULLong ullParam) OVERRIDE;
    virtual UInt OnHandle(Int nEvent, UInt uCount) OVERRIDE; //
    // ICommonRoutine
    virtual bool Start(ICommonServer* pServer) OVERRIDE;
    virtual bool Pause(bool bPause = true) OVERRIDE;
    virtual bool Update(void) OVERRIDE;
    virtual void Stop(void) OVERRIDE;

    virtual UInt     GetThread(void) OVERRIDE;//
    virtual Socket_t GetSocket(UInt uType, UInt uId) OVERRIDE;
    virtual bool     SetTimeout(UInt uTimeout = 0) OVERRIDE;

    virtual bool AddQueue(Int nEvent, uintptr_t utData = 0, ULLong ullParam = 0, QUEUE_TYPE eType = QUEUE_TYPE_NONE) OVERRIDE;
    virtual bool AddQueue(Int nEvent, CEventBase& EventRef, ULLong ullParam = 0, QUEUE_TYPE eType = QUEUE_TYPE_REFCOUNT) OVERRIDE;
    virtual bool AddQueue(Int nEvent, CStream& Stream, ULLong ullParam = 0) OVERRIDE;
private:
    bool  LoadExtConfig(bool bUpdate = false);
    bool  LoadExtRoutineId(CKVNode& Root, bool bUpdate);
    bool  LoadExtSessionType(CKVNode& Root, bool bUpdate);
    bool  LoadExtBusiness(CKVNode& Root);
private:
    // "ServerInfo"开关打开
    bool  SetServiceSocket(UInt uId, ULLong ullParam);
    bool  ClearServiceSocket(UInt uId);

    bool  SetGateSocket(UInt uId, ULLong ullParam);
    bool  ClearGateSocket(UInt uId);

    bool  AddServiceRID(ULLong ullParam, ULLong ullId);
    bool  RemoveServiceRID(ULLong ullParam, ULLong ullId);
    bool  RemoveServiceAllRID(ULLong ullParam, ARY_ROUTINEID& aRID);

    Socket_t GetRoutineIdSocket(ULLong ullRoutineId);

    bool  OnTransferAuthor(CEventBase& EventRef, ULLong ullParam);

    bool  OnLinkRoutineId(CEventBase& EventRef, ULLong ullParam);
    bool  OnUnlinkRoutineId(CEventBase& EventRef, ULLong ullParam);
    bool  OnUnlinkAllRoutineId(ARY_ROUTINEID& aRID, UInt uId, ULLong ullParam);

    bool  OnExternalLogout(CEventBase& EventRef, ULLong ullParam);

    bool  OnTransferRoutine(Int nEvent, CEventBase& EventRef, ULLong ullParam);
private:
    ICommonServer*         m_pServer;         ///< 框架例程处理对应的服务器
    time_t                 m_tExtConfig;      ///< 扩展配置文件修改时间
    Int                    m_nTime;           ///< update()倍数次进行配置文件修改检测
    Int                    m_nUpdate;         ///< 
    UInt                   m_uThreads;        ///< [1, cores]
    UInt                   m_uTimeout;        ///< 异步事件队列工作线程超时检测的时间, 单位[S];
    //-------------------------------------------------------------
    bool                   m_bEnableLink;     ///< 是否允许业务服务器连接时注册业务功能ID
    bool                   m_bTypeCheck;      ///< 是否开启外网端类型和能连接的RID的检测

    ROUTINEID_MAP_CHAIN    m_RoutineId;
    TYPE_RID_MAP_CHAIN     m_TypeRId;

    RID_SOCKET_MAP_CHAIN   m_RIdSocket;
    SOCKET_RID_MAP         m_SocketRId;

    ID_MAP_CHAIN           m_ServiceId;
    ID_MAP_CHAIN           m_GateId;
    //-------------------------------------------------------------
    CEventQueuePtr         m_EventQueuePtr;   ///< 事件队列
    CCommonRoutinePtr      m_BusinessPtr;     ///< 和产品业务相关的
};

INLINE CMasterRoutine::CMasterRoutine(void)
: m_pServer(nullptr)
, m_tExtConfig(0)
, m_nTime(DATAD_UPDATE)
, m_nUpdate(0)
, m_uThreads(0)
, m_uTimeout(0)
, m_bEnableLink(true)
, m_bTypeCheck(false)
{
    DEV_DEBUG(TF(" + %s new instance at %p"), GetRTTI().GetName(), this);
}

INLINE CMasterRoutine::~CMasterRoutine(void)
{
    DEV_DEBUG(TF(" - %s delete instance at %p"), GetRTTI().GetName(), this);
}

INLINE UInt CMasterRoutine::OnHandle(Int, UInt)
{
    return RET_FAIL;
}

INLINE UInt CMasterRoutine::GetThread(void)
{
    return m_uThreads;
}

#endif // __ROUTINE_IMP_H__
